#include "head.h"

int init_tcp(char *ip,char *port)
{
	int sfd;
	struct sockaddr_in server_addr;
	
	if((sfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
		perror("Fail to socket");
		exit(EXIT_FAILURE);
	}
	bzero(&server_addr,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port   = htons(atoi(port));
	server_addr.sin_addr.s_addr = inet_addr(ip);

	if(bind(sfd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
	{
		perror("Fail to bind");
		exit(EXIT_FAILURE);
	}
	
	listen(sfd,5);
	printf("listen....\n");
	return sfd;
}
//.server ip port db
//数据库中已经手动创建了2个表：user_table,word_table
//注：由于我们后面函数要传承，故这里的const应该去掉
int main(int argc, char *argv[])
{
	int i,ret;	
    pid_t pid;
	sqlite3 *pdb;
	int sfd,cfd;
	int len = sizeof(struct sockaddr);
	struct sockaddr_in cli_addr;

	if(argc < 3)
	{
		fprintf(stderr,"Usage : %s ip port system.db.\n",argv[0]);
		exit(EXIT_FAILURE);
	}

	

	if(sqlite3_open(argv[3],&pdb) != SQLITE_OK)
	{
		fprintf(stderr,"sqlite3 open %s : %s.\n",argv[3],sqlite3_errmsg(pdb));
		exit(EXIT_FAILURE);
	}

	//初始化tcp连接，得到监听套接字
	sfd = init_tcp(argv[1],argv[2]);

	//创建epoll实例
	int epfd=epoll_create(1);
	if(epfd==-1)
	{
		perror("epoll():");
		exit(EXIT_FAILURE);
	}
	struct epoll_event ev;
	ev.events=EPOLLIN;
	ev.data.fd=sfd;
	if((ret=epoll_ctl(epfd,EPOLL_CTL_ADD,sfd,&ev))==-1)
	{
		perror("epoll_ctl():");
		exit(EXIT_FAILURE);
	}
	struct epoll_event res_ev[10];
	while(1)
	{
		//判断对应文件描述符是否就绪
		if((ret=epoll_wait(epfd,res_ev,10,500))==-1)
		{
			perror("epoll_wait():");
			exit(EXIT_FAILURE);
		}else if(ret==0)
		{
			printf("Timeout\n");
		}else if(ret>0)
		{
			for(i=0;i<ret;i++)
			{
				//表示sfd就绪
				if(res_ev[i].data.fd==sfd)
				{
					//建立连接，返回新的套接字描述符
					if((cfd=accept(sfd,(struct sockaddr *)&cli_addr,&len))==-1)
					{
						perror("accept()");
						exit(EXIT_FAILURE);
					}
					printf("IP:%s,PORT:%d\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
					struct epoll_event cli_ev;
					//监测sfd是否可读
					cli_ev.events=EPOLLIN;
					cli_ev.data.fd=cfd;
					//添加文件描述符到结构体数组中
					epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&cli_ev);
				}else{
					if(do_client(res_ev[i].data.fd,pdb)==0)
					{
						close(res_ev[i].data.fd);
						epoll_ctl(epfd,EPOLL_CTL_DEL,res_ev[i].data.fd,NULL);
					}
				}

			}
		}
	}
close(sfd);
return 0;
}

